
using System.Collections.Generic;
using System.ComponentModel;
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;

using CIndicators;
using CStock;
using CUtil;

namespace CStock
{
	/// <summary>
	/// this class is abstract mainly because of the ID property, which sets also the path,which has to be either 
	/// Daily or Intraday
	/// </summary>
    public class DataClassFactory : Factory, IDataClassFactory 
	{
        [System.Xml.Serialization.XmlIgnoreAttribute()]


        IDataClassDaily dataClassDaily;


        private int numberOfDataItems;

        double shareValue_Initial;
        


		#region constructor

		public DataClassFactory()
		{
            
            dataClassDaily = new DataClassDaily();
            this.stockObjectBase = dataClassDaily as StockObjectBase;
            
        }

        #endregion


       
        public int NumberOfDataItems
        {
            get
            {
                return numberOfDataItems;
            }
            set
            {
                numberOfDataItems  = value;
            }
        }
        public double ShareValue_Initial
        {
            get
            {
                return shareValue_Initial;
            }
            set
            {
                shareValue_Initial = value;
            }
        }


        
		
		#region Methods


        private bool Create_SampleQuotes_Daily_Intraday(double quoteStart, int myNumberOfDataItems, double randomPercentageDaily, double randomPercentageIntraday)
        {
            this.numberOfDataItems = myNumberOfDataItems;
            
            //set the quoteStart so that the start value is different than random ...
            //this.numberOfDataItems = 1;
            //double quoteStart = Convert.ToDouble(CUtil.RandomGenerator.Random(5, 200));
            //if (this.shareValue_Initial > 0)
            //    quoteStart = shareValue_Initial;

            this.Create_SampleQuotes_Daily(quoteStart, randomPercentageDaily, myNumberOfDataItems);
            this.Create_SampleQuotes_Intraday(quoteStart, randomPercentageIntraday, myNumberOfDataItems);
            return true;
        }
        /// <summary>
        /// adds test data - a quote between 5 and 200
        ///with a deviation of 50%
        /// </summary>
        /// <param name="numberOfItems"></param>
        /// <returns></returns>
        public bool Create_TestData(int numberOfValues)
        {
            this.numberOfDataItems = numberOfValues;
            double quoteStart = Convert.ToDouble(CUtil.RandomGenerator.Random(5, 200));
            if (this.shareValue_Initial > 0)
                quoteStart = shareValue_Initial;

            double randomPercentageDaily = 2;
            double randomPercentageIntraday = 0.02f;



            return Create_SampleQuotes_Daily_Intraday(quoteStart, numberOfDataItems, randomPercentageDaily, randomPercentageIntraday);

        }
        public override bool Create_TestData()
        {
            this.numberOfDataItems = 100;
            return Create_TestData(numberOfDataItems);



        }
        public IDataItem Create_NewDataClass_And_TestData(string sharePrefix, double randomMoney, int numberOfValues)
        {
            PasswordGenerator pw = new PasswordGenerator(false);
            string str = pw.Generate();
            this.Create(sharePrefix + "_" + str);
            
            double randomPercentageDaily = 2;
            double randomPercentageIntraday = 0.02f;


            this.Create_SampleQuotes_Daily_Intraday(randomMoney, numberOfValues, randomPercentageDaily, randomPercentageIntraday);


            //------------------------------------
            //DataClass dclass = this.StockObjectBase as DataClass;
                            

            IDataItem dataItem = new DataItem();
            dataItem.ID = this.StockObjectBase.ID;
            dataItem.DataClass = this.StockObjectBase as DataClassDaily;

            return dataItem;


        }
        public IDataItem Create_TestData_Old(string sharePrefix, double randomMoney)
        {
            
            PasswordGenerator pw = new PasswordGenerator(false);
            string str = pw.Generate();
            this.Create(sharePrefix + "_" + str);

            this.Create_TestData();
            DataClass dclass = this.StockObjectBase as DataClass;


            IQuoteBase q = dclass.QuoteCollection[0] as IQuoteBase;
            dclass.TotalNumberOverall = Convert.ToInt32(randomMoney / q.CLOSEc);


            IDataItem dataItem = new DataItem();
            dataItem.ID = this.StockObjectBase.ID;
            dataItem.DataClass = this.StockObjectBase as DataClassDaily;

            return dataItem;

        }
        #endregion

        private void Create_SampleQuotes_Daily(double startValue, double randomPercentage, int myNumberOfDataItems)
        {
            this.numberOfDataItems = myNumberOfDataItems;

            this.dataClassDaily.SeriesClose = new List<double>();
            this.dataClassDaily.SeriesHigh = new List<double>();
            this.dataClassDaily.SeriesLow = new List<double>();
            this.dataClassDaily.SeriesOpen = new List<double>();
            this.dataClassDaily.SeriesVolume = new List<System.Int64>();
            this.dataClassDaily.SeriesTime = new List<DateTime>();
            
            double start = startValue;



            DateTime dtStart = DateTime.Now.AddDays(-numberOfDataItems);

            for (int i = 0; i < numberOfDataItems; i++)
            {
                DateTime dtNew = dtStart.AddDays(i).Date;
                if (Create_Quote_Random(this.dataClassDaily, ref start, dtNew, randomPercentage))
                {
                    
                    //dtNew = dtNew.Date;

                    
                }
            }

        }
        private static double GetRandomValue(double start, double randomMultiplicator)
        {
            double startMin = start - start * randomMultiplicator;
            double startMax = start + start * randomMultiplicator;
            //open = old start


            int startMinInt = Convert.ToInt32(startMin * 1000f);
            int startMaxInt = Convert.ToInt32(startMax * 1000f);

            int startInt = Convert.ToInt32(RandomGenerator.Random(startMinInt, startMaxInt));

            start = Convert.ToDouble(startInt / 1000f);
            start = CUtil.FormatNumbers.FormatFloatWithTwoDigits(start);
            return start;
        }
        public static bool Create_Quote_Random(IDataProvider dc, ref double start,  DateTime dtNew, double randomPercentage)
        {
            try
            {
                double randomMultiplicator = randomPercentage / 100f;
                if (randomMultiplicator <= 0)
                    System.Diagnostics.Debug.WriteLine("Random Multiplicator = 0");

                double open = start;
                dc.SeriesOpen.Add(open);


                start = GetRandomValue(start, randomMultiplicator);

                dc.SeriesClose.Add(start);

                double high = GetRandomValue(open, randomMultiplicator);
                if (high < start)
                    high = start;

                double low = GetRandomValue(open, randomMultiplicator);

                
                if (low > start)
                    low = start;
                
                dc.SeriesHigh.Add(high);
                dc.SeriesLow.Add(low);

                dc.SeriesTime.Add(dtNew);
                double volVal = Convert.ToDouble(CUtil.RandomGenerator.Random(100, 10000));

                dc.SeriesVolume.Add(Convert.ToInt64(volVal));

                return true;

            }
            catch (Exception ex)
            {
                Debug.Assert(false, "Error creating random values " + ex.Message);
                return false;
            }
            //this.dataClassDaily.SeriesVolume.Add(i * 5);
        }
        public void Create_SampleQuotes_Intraday(double startValue, double randomPercentage, int myNumberOfDataItems)
        {

            this.numberOfDataItems = myNumberOfDataItems;

            double start = startValue;

            this.dataClassDaily.DataClassIntraday.SeriesOpen = new List<double>();
            this.dataClassDaily.DataClassIntraday.SeriesTime = new List<DateTime>();

            DateTime dStart = DateTime.Now;
            dStart = new DateTime(dStart.Year, dStart.Month, dStart.Day, 9, 0, 0);

            //numberOfDataItems  for the 8 hours of the day - 
            if (numberOfDataItems > 480)
                numberOfDataItems = 480;
            int numberOfMinutesToAdd = 480/numberOfDataItems ;


            for (int i = 0; i < numberOfDataItems; i++)
            {
                dStart = dStart.AddMinutes(numberOfMinutesToAdd);
                if (Create_Quote_Random(this.dataClassDaily.DataClassIntraday, ref start, dStart, randomPercentage))
                {

                    
                  
                }

              


            }

        }
        public static bool DeSerialize_DC(string id, ref object o)
        {

            DataClassDaily d = new DataClassDaily();
            d.ID = id;
            //d.Path = path;


            o = new DataClassDaily();


            try
            {
                if (d.DeSerialize(ref o))
                {
                    if (o != null)
                        d = o as DataClassDaily;
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("Could not get data from disk for: " + id.ToString() + "; error is: " + ex.Message);
                return false;

            }
        }
    
        public bool SetTradeOrders()
        {
            return true;
        }

        public override bool RemoveAll()
        {
            return XMLSerializable.RemoveAllData(this.stockObjectBase.Path);

        }

        /// <summary>
        /// attention - new object variable for dataClass!!
        /// </summary>
        /// <returns></returns>
        public override bool DeSerialize()
        {
            if (base.DeSerialize())
            {
               
                this.dataClassDaily = this.stockObjectBase as IDataClassDaily;

                return true;
            }
            return false;



        }

    }
}
